package com.guochenglang.www.service.impl;

import com.guochenglang.www.dao.*;
import com.guochenglang.www.pojo.*;
import com.guochenglang.www.service.ArticleService;
import com.guochenglang.www.service.BaseService;
import com.guochenglang.www.service.anotate.Affair;
import com.guochenglang.www.util.DangerWordBoolean;
import com.guochenglang.www.util.GetTable;
import com.guochenglang.www.util.MyDependency;
import com.guochenglang.www.util.lru.MyCapacity;

import java.sql.SQLException;
import java.util.*;

/**
 * 文章业务层
 *
 * @author GuoChenglang
 */
public class ArticleServiceImpl implements ArticleService {
    private static final BaseDao BASE_DAO = MyDependency.returnObject(BaseDao.class);
    private static final ArticleDao ARTICLE_DAO = MyDependency.returnObject(ArticleDao.class);
    private static final LikesDao LIKES_DAO = MyDependency.returnObject(LikesDao.class);
    private static final FilesDao FILES_DAO = MyDependency.returnObject(FilesDao.class);
    private static final TracesDao TRACES_DAO = MyDependency.returnObject(TracesDao.class);

    /**
     * 根据日期排序文章
     *
     * @param page 页数
     * @param num  每页几条文章
     * @return 文章列表
     */
    @Override
    public Page<Article> allArticleByDate(Integer page, Integer num) throws SQLException, InterruptedException, IllegalAccessException, InstantiationException {
        //搜索公开的知识库
        Base base = new Base();
        base.setIsPublic(1);
        ArrayList<Base> bases = BASE_DAO.baseSelect(base);
        List<Integer> baseId = new ArrayList<>();
        for (Base basis : bases) {
            baseId.add(basis.getId());
        }
        //搜寻所有文章
        ArrayList<Article> articles = ARTICLE_DAO.articleSelectByLimit(page, num, new Article(), "creatTime", "DESC");
        //储存结果
        ArrayList<Article> newArticles = new ArrayList<>();
        for (Article article : articles) {
            //该对象是公开的文章，添加进结果
            System.out.println(article.getBaseId() + " " + baseId);
            if (baseId.contains(article.getBaseId())) {
                newArticles.add(article);
            }
        }
        //将结果封装进Page类中
        Page<Article> articlePage = new Page<>(num, this.getSize(), newArticles, page);
        return articlePage;

    }

    /**
     * 根据点赞数排列文章
     *
     * @param page 页码
     * @param num  每页几条
     * @return 文章列表
     */
    @Override
    public Page<Article> allArticleByLike(Integer page, Integer num) throws SQLException, InterruptedException, IllegalAccessException, InstantiationException {
        //搜索非公开的知识库
        Base base = new Base();
        base.setIsPublic(2);
        System.out.println(base);
        ArrayList<Base> bases = BASE_DAO.baseSelect(base);
        List<Integer> baseId = new ArrayList<>();
        for (Base basis : bases) {
            baseId.add(basis.getId());
        }
        //搜索所有文章
        ArrayList<Article> articles = ARTICLE_DAO.articleSelect(new Article());
        ArrayList<Article> newArticles = new ArrayList<>();
        //创建<文章，喜欢数>的有序map集合
        LinkedHashMap<Article, Integer> map = new LinkedHashMap<>();
        for (Article article : articles) {
            if (!baseId.contains(article.getBaseId())) {
                map.put(article, LIKES_DAO.likesSelect(new Likes(null, article.getId(), null)).size());
            }
        }
        System.out.println(map);
        List<Map.Entry<Article, Integer>> entries = new ArrayList<>(map.entrySet());
        //利用sort比较点赞数,进行排序
        Collections.sort(entries, new Comparator<Map.Entry<Article, Integer>>() {
            @Override
            public int compare(Map.Entry<Article, Integer> o1, Map.Entry<Article, Integer> o2) {
                return o2.getValue() - o1.getValue();
            }
        });
        for (Map.Entry<Article, Integer> entry : entries) {
            newArticles.add(entry.getKey());
        }
        //获得起始的索引
        int start = (page - 1) * num;
        //获得最后的索引
        int last = start + num;
        if (start > newArticles.size()) {
            return new Page<>();
        } else if (last > newArticles.size()) {
            last = newArticles.size();
        }

        List<Article> newArticle = newArticles.subList(start, last);
        //将结果封装进Page类中
        return new Page<>(num, this.getSize(), newArticle, page);

    }

    /**
     * 阅读文章
     *
     * @param article 文章信息
     * @return 文章信息
     */
    @Override
    public Article readArticle(Article article) {
        try {
            return ARTICLE_DAO.articleSelect(article).get(0);
        } catch (SQLException | IllegalAccessException | InstantiationException | InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 发表文章
     *
     * @param article 文章信息
     * @return 主键
     */
    @Affair
    @Override
    public int publishArticle(Article article) throws SQLException, InterruptedException, IllegalAccessException {
        String title = article.getTitle();
        String content = article.getText();
        //敏感词判断
        if (DangerWordBoolean.isDangerWord(title) || DangerWordBoolean.isDangerWord(content)) {
            return -1;
        }
        return ARTICLE_DAO.insertArticle(article);
    }

    /**
     * 上传附件
     *
     * @param files 图片信息
     * @return 主键
     */
    @Affair
    @Override
    public int uploadFiles(Files files) throws SQLException, InterruptedException, IllegalAccessException {
        return FILES_DAO.insertFiles(files);
    }

    /**
     * 获得列表信息
     *
     * @param articleId 文章id
     * @return 附件列表
     */
    @Override
    public ArrayList<Files> showFiles(Integer articleId) throws SQLException, InterruptedException, IllegalAccessException, InstantiationException {
        return FILES_DAO.filesSelect(new Files(null, null, articleId));
    }

    /**
     * 获得所有文章个数
     *
     * @return 所有文章数
     */
    @Override
    public int getSize() throws SQLException, InterruptedException, IllegalAccessException, InstantiationException {
        ArrayList<Base> bases = MyDependency.returnObject(BaseService.class).baseSelectPublic();
        int num = 0;
        for (Base basis : bases) {
            //封装条件
            Article conditions = new Article();
            //获得公开知识库的文章
            conditions.setBaseId(basis.getId());
            ArrayList<Article> articles = ARTICLE_DAO.articleSelect(conditions);
            num += articles.size();
        }
        return num;
    }

    /**
     * 获得某个知识库的所有文章
     *
     * @return 文章集合
     */
    @Override
    public ArrayList<Article> baseArticle(Integer baseId) throws SQLException, InterruptedException, IllegalAccessException, InstantiationException {
        return MyDependency.returnObject(ArticleDao.class).articleSelect(new Article(null, baseId, null, null, null, null));
    }

    /**
     * 删除文章
     *
     * @param articleId 文章的id
     * @return 删除行数
     */
    @Affair
    @Override
    public int deleteArticle(Integer articleId) throws SQLException, InterruptedException, IllegalAccessException, InstantiationException {
        Article conditions = new Article();
        conditions.setId(articleId);
        Traces conditionsTrace = new Traces();
        conditionsTrace.setArticleId(articleId);
        //删除浏览记录
        TRACES_DAO.deleteTraces(conditionsTrace);
        return ARTICLE_DAO.deleteArticle(conditions);

    }

    /**
     * 根据id获取文章
     *
     * @param articleId 文章的id
     * @return 具体文章
     */
    @Override
    public Article getArticle(Integer articleId) throws SQLException, InterruptedException, IllegalAccessException, InstantiationException {
        //进入缓存找
        //获取键值
        String key = MyCapacity.getKey(articleId, GetTable.getTable(Article.class));
        Article article = (Article) MyCapacity.get(key);
        if (article == null) {
            //若缓存没有
            Article conditions = new Article();
            conditions.setId(articleId);
            //搜寻数据库
            ArrayList<Article> articles = ARTICLE_DAO.articleSelect(conditions);
            if (!articles.isEmpty()) {
                //加入缓存
                article = articles.get(0);
                MyCapacity.put(key, article);
            }
        }
        return article;

    }

}
